package com.imis.base.util.form;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.imis.base.constant.CommonConstant;
import com.imis.base.constant.ControlTypeConstant;
import com.imis.base.constant.DataBaseConstant;
import com.imis.base.constant.ValidationMessageConstant;
import com.imis.base.constant.enums.ArgumentResponseEnum;
import com.imis.base.constant.enums.FormValidPatternEnum;
import com.imis.base.constant.enums.MatchTypeEnum;
import com.imis.base.constant.enums.QueryRuleEnum;
import com.imis.base.util.ConvertUtils;
import com.imis.base.util.CurrentUserUtils;
import com.imis.base.util.SpringContextUtils;
import com.imis.base.util.form.jsonschema.BaseColumn;
import com.imis.base.util.form.jsonschema.BaseCommonProperty;
import com.imis.base.util.form.jsonschema.JsonSchemaDescription;
import com.imis.base.util.form.jsonschema.JsonSchemaUtil;
import com.imis.base.util.form.jsonschema.validate.*;
import com.imis.base.util.form.model.DataPermissionRuleModel;
import com.imis.base.util.table.DataBaseTableUtil;
import com.imis.module.api.model.ro.DictItemsByCodeQueryDTO;
import com.imis.module.online.form.model.po.FormButton;
import com.imis.module.online.form.model.po.FormEnhanceJava;
import com.imis.module.online.form.model.po.FormEnhanceJavaScript;
import com.imis.module.online.form.model.vo.TreeSelectColumn;
import com.imis.module.online.table.dao.TableHeadMapper;
import com.imis.module.online.table.model.po.TableFields;
import com.imis.module.online.table.service.ITableFieldsService;
import com.imis.module.system.model.vo.DictVO;
import com.imis.module.system.service.ISysDictService;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * <p>
 * FormUtil<br>
 * 表单构建工具类
 * </p>
 *
 * @author XinLau
 * @version 1.0
 * @since 2019年03月26日 11:11
 */
@Slf4j
public class FormUtil {

    /**
     * 增强 JavaScript 按钮代码
     */
    private static final String[] ENHANCE_JAVA_SCRIPT_BUTTON_CODE = {"beforeAdd", "beforeEdit", "afterAdd", "afterEdit", "beforeDelete", "afterDelete", "mounted", "created"};

    /**
     * 转化数据规则配置的系统变量
     *
     * @param value - 参数值
     * @param flag  - 参数标志（是否需要加 ''）
     * @return null -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/23 9:21
     */
    private static String convertRuleValue(String value, boolean flag) {
        if (flag) {
            return DataBaseConstant.SINGLE_QUOTE + QueryGenerator.convertRuleValue(value) + DataBaseConstant.SINGLE_QUOTE;
        } else {
            return QueryGenerator.convertRuleValue(value);
        }
    }

    /**
     * 根据数据规则对象 组装SQL
     *
     * @param dataBaseType            - 数据库类型
     * @param dataPermissionRuleModel - 数据规则
     * @param field                   - 字段名
     * @param fieldType               - 字段类型
     * @param stringBuffer            - SQL对象
     */
    private static void addRuleToStringBuffer(final String dataBaseType, final DataPermissionRuleModel dataPermissionRuleModel, final String field, final String fieldType, StringBuffer stringBuffer) {
        QueryRuleEnum rule = QueryRuleEnum.getByValue(dataPermissionRuleModel.getRuleConditions());
        // 判断是否是数值类型
        boolean isNumberField = !OnlineDataBaseHandler.isNumberField(fieldType);
        String value = convertRuleValue(dataPermissionRuleModel.getRuleValue(), isNumberField);
        if (value == null || rule == null) {
            return;
        }
        // 针对 ORACLE 数据库，时间值特殊处理
        if (DataBaseConstant.DB_TYPE_ORACLE.equalsIgnoreCase(dataBaseType)) {
            if (DataBaseConstant.DATE.equals(fieldType)) {
                value = value.replace(DataBaseConstant.SINGLE_QUOTE, DataBaseConstant.EMPTY);
                if (value.length() == 10) {
                    value = getOracleToDateString(value);
                } else {
                    value = getOracleToDateTimeString(value);
                }
            }
        }
        // Query 规则
        switch (rule) {
            case GT:
                // 大于
                stringBuffer.append(DataBaseConstant.SQL_AND).append(field).append(DataBaseConstant.RIGHT_CHEV).append(value);
                break;
            case GE:
                // 大于等于
                stringBuffer.append(DataBaseConstant.SQL_AND).append(field).append(DataBaseConstant.GREATER_THAN_OR_EQUAL_TO).append(value);
                break;
            case LT:
                // 小于
                stringBuffer.append(DataBaseConstant.SQL_AND).append(field).append(DataBaseConstant.LEFT_CHEV).append(value);
                break;
            case LE:
                // 小于等于
                stringBuffer.append(DataBaseConstant.SQL_AND).append(field).append(DataBaseConstant.LESS_THAN_OR_EQUAL_TO).append(value);
                break;
            case EQ:
                // 等于
                stringBuffer.append(DataBaseConstant.SQL_AND).append(field).append(DataBaseConstant.EQUALS).append(value);
                break;
            case NE:
                // 不等于
                stringBuffer.append(DataBaseConstant.SQL_AND).append(field).append(DataBaseConstant.SPACE).append(DataBaseConstant.LEFT_CHEV).append(DataBaseConstant.RIGHT_CHEV).append(DataBaseConstant.SPACE).append(value);
                break;
            case IN:
                // 包含
                stringBuffer.append(DataBaseConstant.SQL_AND).append(field).append(DataBaseConstant.SQL_IN).append(value);
                break;
            case LIKE:
                // 全模糊
                stringBuffer.append(DataBaseConstant.SQL_AND).append(field).append(DataBaseConstant.SQL_LIKE).append(DataBaseConstant.SINGLE_QUOTE).append(DataBaseConstant.PERCENT).append(QueryGenerator.trimSingleQuote(value)).append(DataBaseConstant.PERCENT).append(DataBaseConstant.SINGLE_QUOTE);
                break;
            case LEFT_LIKE:
                // 左模糊
                stringBuffer.append(DataBaseConstant.SQL_AND).append(field).append(DataBaseConstant.SQL_LIKE).append(DataBaseConstant.SINGLE_QUOTE).append(DataBaseConstant.PERCENT).append(QueryGenerator.trimSingleQuote(value)).append(DataBaseConstant.SINGLE_QUOTE);
                break;
            case RIGHT_LIKE:
                // 右模糊
                stringBuffer.append(DataBaseConstant.SQL_AND).append(field).append(DataBaseConstant.SQL_LIKE).append(DataBaseConstant.SINGLE_QUOTE).append(QueryGenerator.trimSingleQuote(value)).append(DataBaseConstant.PERCENT).append(DataBaseConstant.SINGLE_QUOTE);
                break;
            default:
                log.info("-- 查询规则未匹配到 --");
                break;
        }
    }

    /**
     * 获取系统数据库类型
     *
     * @return String - 数据库类型
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/20 13:43
     */
    private static String getDataBaseType() {
        String dataBaseType = DataBaseConstant.EMPTY;
        try {
            dataBaseType = DataBaseTableUtil.getDataBaseType();
        } catch (SQLException throwable) {
            log.error(throwable.getMessage());
        }
        return dataBaseType;
    }

    /**
     * 高级查询格式化 value</br>
     * <li>字符类型加上双引号，数值类型直接返回</li>
     *
     * @param fieldType  - 字段类型
     * @param fieldValue - 字段值
     * @return String - SQL
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/22 17:16
     */
    private static String formatSuperQueryValue(String fieldType, String fieldValue) {
        if (DataBaseConstant.INT.equals(fieldType) || DataBaseConstant.NUMBER.equals(fieldType)) {
            return fieldValue;
        } else if (DataBaseConstant.DATE_.equals(fieldType)) {
            return DataBaseConstant.SINGLE_QUOTE + fieldValue + DataBaseConstant.SINGLE_QUOTE;
        } else {
            if (DataBaseConstant.DB_TYPE_SQL_SERVER.equals(getDataBaseType())) {
                // （SQL SERVER 中文查询，前面必须加 N）
                return CommonConstant.TO_UPPER_CASE_N + DataBaseConstant.SINGLE_QUOTE + fieldValue + DataBaseConstant.SINGLE_QUOTE;
            } else {
                return DataBaseConstant.SINGLE_QUOTE + fieldValue + DataBaseConstant.SINGLE_QUOTE;
            }
        }
    }

    /**
     * 根据数据规则设置超级查询字段 组装SQL
     *
     * @param stringBuilder - SQL对象
     * @param queryRuleEnum - Query 规则
     * @param nativeValue   - 字段原始值（IN 查询）
     * @param value         - 字段值
     * @param fieldType     - 字段类型
     */
    private static void setSuperQueryFieldByRule(StringBuilder stringBuilder, QueryRuleEnum queryRuleEnum, String nativeValue, String value, String fieldType) {
        // 针对 Oracle 数据库，时间值进行特殊处理
        if (DataBaseConstant.DATE_.equals(fieldType)) {
            if (DataBaseConstant.DB_TYPE_ORACLE.equalsIgnoreCase(getDataBaseType())) {
                value = value.replace(DataBaseConstant.SINGLE_QUOTE, DataBaseConstant.EMPTY);
                if (value.length() == 10) {
                    value = getOracleToDateString(value);
                } else {
                    value = getOracleToDateTimeString(value);
                }
            }
        }
        // Query 规则
        switch (queryRuleEnum) {
            case GT:
                // 大于
                stringBuilder.append(DataBaseConstant.RIGHT_CHEV).append(value);
                break;
            case GE:
                // 大于等于
                stringBuilder.append(DataBaseConstant.GREATER_THAN_OR_EQUAL_TO).append(value);
                break;
            case LT:
                // 小于
                stringBuilder.append(DataBaseConstant.LEFT_CHEV).append(value);
                break;
            case LE:
                // 小于等于
                stringBuilder.append(DataBaseConstant.LESS_THAN_OR_EQUAL_TO).append(value);
                break;
            case NE:
                // 不等于
                stringBuilder.append(DataBaseConstant.SQL_NOT_EQUAL_TO).append(value);
                break;
            case IN:
                // 在...中
                stringBuilder.append(DataBaseConstant.SQL_IN).append(DataBaseConstant.LEFT_BRACKET);
                String[] arr = nativeValue.split(DataBaseConstant.COMMA);
                for (int i = 0; i < arr.length; i++) {
                    String str = arr[i];
                    if (StringUtils.isNotBlank(str)) {
                        String val = formatSuperQueryValue(fieldType, str);
                        stringBuilder.append(val);
                        if (i < arr.length - 1) {
                            stringBuilder.append(DataBaseConstant.COMMA);
                        }
                    }
                }
                stringBuilder.append(DataBaseConstant.RIGHT_BRACKET);
                break;
            case LIKE:
                // 包含（SQL SERVER 中文查询，前面必须加 N）
                stringBuilder.append(DataBaseConstant.SQL_LIKE).append(CommonConstant.TO_UPPER_CASE_N).append(DataBaseConstant.SINGLE_QUOTE).append(DataBaseConstant.PERCENT).append(nativeValue).append(DataBaseConstant.PERCENT).append(DataBaseConstant.SINGLE_QUOTE);
                break;
            case LEFT_LIKE:
                // 以..结尾（SQL SERVER 中文查询，前面必须加 N）
                stringBuilder.append(DataBaseConstant.SQL_LIKE).append(CommonConstant.TO_UPPER_CASE_N).append(DataBaseConstant.SINGLE_QUOTE).append(DataBaseConstant.PERCENT).append(nativeValue).append(DataBaseConstant.SINGLE_QUOTE);
                break;
            case RIGHT_LIKE:
                // 以..开始（SQL SERVER 中文查询，前面必须加 N）
                stringBuilder.append(DataBaseConstant.SQL_LIKE).append(CommonConstant.TO_UPPER_CASE_N).append(DataBaseConstant.SINGLE_QUOTE).append(nativeValue).append(DataBaseConstant.PERCENT).append(DataBaseConstant.SINGLE_QUOTE);
                break;
            case EQ:
                // 等于 （默认值）
            default:
                stringBuilder.append(DataBaseConstant.EQUALS).append(value);
        }
    }

    /**
     * 拼接高级查询条件字段
     *
     * @param stringBuilder - SQL对象
     * @param fieldName     - 字段名称
     * @param parameter     - 其他参数
     * @param matchTypeEnum - 查询链接规则（AND、OR）
     * @param childTable    - 子表（null 代表是主表）
     * @param isFirst       - 是否首字段
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/22 17:16
     */
    private static void spliceSuperQueryField(StringBuilder stringBuilder, String fieldName, JSONObject parameter, MatchTypeEnum matchTypeEnum, JSONObject childTable, Boolean isFirst) {
        if (!isFirst) {
            stringBuilder.append(DataBaseConstant.SPACE).append(matchTypeEnum.getValue()).append(DataBaseConstant.SPACE);
        }
        String type = parameter.getString("type");
        String nativeValue = parameter.getString("value");
        String value = formatSuperQueryValue(type, nativeValue);
        QueryRuleEnum rule = QueryRuleEnum.getByValue(parameter.getString("rule"));
        if (rule == null) {
            // 默认是 等于
            rule = QueryRuleEnum.EQ;
        }
        // 子表名不为空则查询子表
        if (childTable != null) {
            String childTableName = childTable.getString(DataBaseConstant.CHILD_TABLE_NAME);
            String childTableField = childTable.getString(DataBaseConstant.CHILD_TABLE_FIELD);
            // String mainTableName = childTable.getString(DataBaseConstant.MAIN_TABLE_NAME);
            String mainTableField = childTable.getString(DataBaseConstant.MAIN_TABLE_FIELD);
            stringBuilder.append(DataBaseConstant.LEFT_BRACKET)
                    .append(mainTableField).append(DataBaseConstant.SQL_IN).append(DataBaseConstant.LEFT_BRACKET)
                    .append(DataBaseConstant.SQL_SELECT).append(childTableField)
                    .append(DataBaseConstant.SQL_FROM).append(childTableName)
                    .append(DataBaseConstant.SQL_WHERE).append(fieldName);
            setSuperQueryFieldByRule(stringBuilder, rule, nativeValue, value, type);
            stringBuilder.append(DataBaseConstant.RIGHT_BRACKET).append(DataBaseConstant.RIGHT_BRACKET);
        } else {
            stringBuilder.append(fieldName);
            setSuperQueryFieldByRule(stringBuilder, rule, nativeValue, value, type);
        }
    }

    /**
     * 根据正则替换 JavaScript 增强
     *
     * @param enhanceJavaScript - JavaScript 增强
     * @param temp              - ButtonCode
     * @return String - JavaScript 增强
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/20 15:01
     */
    private static String getEnhanceJavaScriptString(String enhanceJavaScript, String temp) {
        Pattern p = Pattern.compile(DataBaseConstant.LEFT_BRACKET + temp + "\\s*\\(row\\)\\s*\\{)");
        Matcher m = p.matcher(enhanceJavaScript);
        if (m.find()) {
            enhanceJavaScript = enhanceJavaScript.replace(m.group(0), temp + "(that,row){const getAction=this._getAction,postAction=this._postAction,deleteAction=this._deleteAction;");
        } else {
            Pattern p2 = Pattern.compile(DataBaseConstant.LEFT_BRACKET + temp + "\\s*\\(\\)\\s*\\{)");
            Matcher m2 = p2.matcher(enhanceJavaScript);
            if (m2.find()) {
                enhanceJavaScript = enhanceJavaScript.replace(m2.group(0), temp + "(that){const getAction=this._getAction,postAction=this._postAction,deleteAction=this._deleteAction;");
            }
        }
        return enhanceJavaScript;
    }

    /**
     * 根据数据库表字段信息获取验证信息
     *
     * @param tableFields - 数据库表字段信息
     * @return JSONArray - 验证信息
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/20 15:01
     */
    private static JSONArray getValidateRules(TableFields tableFields) {
        JSONArray array = new JSONArray();
        if (CommonConstant.INTEGER_NO.equals(tableFields.getIsNull()) || CommonConstant.INTEGER_YES.equals(tableFields.getFieldMustInput())) {
            JSONObject json = new JSONObject();
            json.put("required", true);
            json.put("message", tableFields.getFieldTxt() + ValidationMessageConstant.EMPTY_ERR);
            array.add(json);
        }
        if (ConvertUtils.isNotEmpty(tableFields.getFieldValidType())) {
            JSONObject json2 = new JSONObject();
            if ("only".equals(tableFields.getFieldValidType())) {
                // 唯一校验 子表不支持
                json2.put("pattern", null);
            } else {
                json2.put("pattern", tableFields.getFieldValidType());
            }
            json2.put("message", tableFields.getFieldTxt() + ValidationMessageConstant.FORMAT_ERR);
            array.add(json2);
        }
        return array;
    }

    /**
     * 查询 Dict 字段的选项信息
     *
     * @param tableFields - 数据库表字段信息
     * @return List<DictVO> - 简化版字典对象
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/20 15:01
     */
    private static List<DictVO> queryDictFieldOptions(TableFields tableFields) {
        ISysDictService sysDictService = SpringContextUtils.getBean(ISysDictService.class);
        // 校验 ISysDictService 是否获取成功
        ArgumentResponseEnum.NULL_POINTER_EXCEPTION.assertNotNull(sysDictService);
        List<DictVO> include = new ArrayList<>();
        if (ConvertUtils.isNotEmpty(tableFields.getDictTable())) {
            DictItemsByCodeQueryDTO sysDictItemsByCodeQuery = new DictItemsByCodeQueryDTO();
            sysDictItemsByCodeQuery.setTable(tableFields.getDictTable());
            sysDictItemsByCodeQuery.setTextField(tableFields.getDictText());
            sysDictItemsByCodeQuery.setCodeField(tableFields.getDictField());
            include = sysDictService.queryTableDictItemsByCode(sysDictItemsByCodeQuery);
        } else if (ConvertUtils.isNotEmpty(tableFields.getDictField())) {
            include = sysDictService.queryDictItemsByDictCode(tableFields.getDictField());
        }
        return include;
    }

    /**
     * 给系统字段赋值
     *
     * @param tableFields  - 数据库表字段信息
     * @param requestJson  - 表单数据
     * @param systemFields - 系统字段
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/23 13:37
     */
    private static void initSystemFiles(TableFields tableFields, JSONObject requestJson, String... systemFields) {
        // 1.判断系统字段是否显示于前端 不显示前端 则设定默认值
        // 2.如果显示那么 判断 JSON 数据中是否有数据 没有数据则设定默认值
        String key = tableFields.getFieldName();
        boolean need = Boolean.FALSE;
        for (String field : systemFields) {
            if (key.toUpperCase().equals(field)) {
                if (CommonConstant.INTEGER_YES.equals(tableFields.getIsShowForm())) {
                    if (requestJson.get(key) == null) {
                        need = Boolean.TRUE;
                    }
                } else {
                    tableFields.setIsShowForm(CommonConstant.INTEGER_YES);
                    need = Boolean.TRUE;
                }
                if (need) {
                    switch (field) {
                        case DataBaseConstant.CREATE_BY_FIELD:
                        case DataBaseConstant.UPDATE_BY_FIELD:
                            // 获取当前登录用户编号
                            Long userId = CurrentUserUtils.getUserIdFormHttpServletRequest();
                            requestJson.put(key, ConvertUtils.isEmpty(userId) ? StringPool.ZERO : userId);
                            break;
                        case DataBaseConstant.CREATE_TIME_FIELD:
                        case DataBaseConstant.UPDATE_TIME_FIELD:
                            tableFields.setFieldShowType(DataBaseConstant.DATE_TIME_);
                            requestJson.put(key, LocalDateTime.now());
                            break;
                        case DataBaseConstant.ORGANIZATION_CODE_FIELD:
                            // 替换为系统用户登录所使用的机构编码
                            Long organizationId = CurrentUserUtils.getOrganizationIdFormHttpServletRequest();
                            requestJson.put(key, ConvertUtils.isEmpty(organizationId) ? StringPool.ZERO : organizationId);
                            break;
                        default:
                            break;
                    }
                }
                break;
            }
        }
    }

    /**
     * Clob字段转 String
     *
     * @param clob - Clob
     * @return String - ClobString
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/24 14:32
     */
    private static String clobToString(Clob clob) {
        String clobString = DataBaseConstant.EMPTY;
        try {
            Reader inStream = clob.getCharacterStream();
            char[] c = new char[(int) clob.length()];
            inStream.read(c);
            clobString = new String(c);
            inStream.close();
        } catch (IOException | SQLException e) {
            log.error(e.getMessage());
        }
        return clobString;
    }

    /**
     * 获取必须要处理的列 POPUP回调的列但是该列隐藏
     *
     * @param tableFieldList - 数据库表字段信息
     * @return java.util.Set<java.lang.String>
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/20 8:45
     */
    private static Set<String> getNeedHandleField(List<TableFields> tableFieldList) {
        Set<String> set = new HashSet<>();
        for (TableFields item : tableFieldList) {
            if (ControlTypeConstant.POPUP.equals(item.getFieldShowType())) {
                String dictText = item.getDictText();
                if (dictText != null && !dictText.equals(DataBaseConstant.EMPTY)) {
                    set.addAll(Arrays.stream(dictText.split(DataBaseConstant.COMMA)).collect(Collectors.toSet()));
                }
            }
            if (ControlTypeConstant.DICT_TREE.equals(item.getFieldShowType())) {
                String dictText = item.getDictText();
                if (ConvertUtils.isNotEmpty(dictText)) {
                    set.add(dictText);
                }
            }
        }
        for (TableFields item : tableFieldList) {
            String key = item.getFieldName();
            if (set.contains(key) && CommonConstant.INTEGER_YES.equals(item.getIsShowForm())) {
                // 如果字段是显示的就没必要在这里处理了
                set.remove(key);
            }
        }
        return set;
    }

    /**
     * 判断是否需要处理字典配置
     *
     * @param filedShowType - 表单控件类型
     * @return Boolean
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/20 10:30
     */
    private static Boolean hasDictConfig(String filedShowType) {
        Boolean hasDictConfig = Boolean.FALSE;
        switch (filedShowType) {
            case "list":
            case "radio":
            case ControlTypeConstant.CHECK_BOX:
            case "list_multi":
            case ControlTypeConstant.SELECT_SEARCH:
                hasDictConfig = Boolean.TRUE;
                break;
            default:
                break;
        }
        return hasDictConfig;
    }

    /**
     * 判断字段是否有效
     *
     * @param fieldName      - 字段
     * @param tableFieldList - 数据库表字段信息
     * @return null -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/24 13:35
     */
    private static Boolean existFieldName(String fieldName, List<TableFields> tableFieldList) {
        // return tableFieldList.stream().anyMatch(tableFields -> fieldName.equals(tableFields.getFieldName()));
        return tableFieldList.stream().anyMatch(tableFields -> fieldName.equalsIgnoreCase(tableFields.getFieldName()));
    }

    /**
     * 获取级联下拉组件的其他组件配置
     *
     * @param linkDownProperty -级联下拉
     * @param tableFieldList   - 数据库表字段信息
     * @param excludeFields    - 需要排除字段，级联下拉，已经加载的不再加载
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/24 14:47
     */
    private static void getLinkDownOtherField(LinkDownPropertyBase linkDownProperty, List<TableFields> tableFieldList, List<String> excludeFields) {
        String dictTable = linkDownProperty.getDictTable();
        JSONObject dictTableJson = JSONObject.parseObject(dictTable);
        String linkField = dictTableJson.getString("linkField");
        List<BaseColumn> baseColumnArrayList = new ArrayList<>();
        if (ConvertUtils.isNotEmpty(linkField)) {
            String[] linkFieldArray = linkField.split(DataBaseConstant.COMMA);
            for (TableFields tableFields : tableFieldList) {
                String fieldName = tableFields.getFieldName();
                for (String key : linkFieldArray) {
                    if (key.equals(fieldName)) {
                        excludeFields.add(fieldName);
                        baseColumnArrayList.add(new BaseColumn(tableFields.getFieldTxt(), fieldName));
                        break;
                    }
                }
            }
        }
        linkDownProperty.setOtherColumns(baseColumnArrayList);
    }

    /**
     * 获取 EditableTable 列需要的类型字符串
     */
    private static String getEditableTableColumnsType(TableFields tableFields) {
        String viewType;
        switch (tableFields.getFieldShowType()) {
            case "list":
                viewType = "select";
                break;
            case "int":
            case "double":
            case "BigDecimal":
                viewType = "inputNumber";
                break;
            case ControlTypeConstant.SWITCH:
            case ControlTypeConstant.CHECK_BOX:
            case ControlTypeConstant.IMAGE:
            case ControlTypeConstant.POPUP:
            case ControlTypeConstant.SELECT_SEARCH:
            case "file":
            case "radio":
            case "list_multi":
            case "datetime":
            case "date":
                viewType = tableFields.getFieldShowType();
                break;
            default:
                viewType = ControlTypeConstant.INPUT;
                break;
        }
        return viewType;
        /**
         { title: '文本框', value: 'text' },
         { title: '密码', value: 'password' },
         { title: '单选框', value: 'radio' },
         { title: '多选', value: 'checkbox' },
         { title: '日期(yyyy-MM-dd)', value: 'date' },
         { title: '日期（yyyy-MM-dd HH:mm:ss）', value: 'datetime' },
         { title: '文件', value: 'file' },
         { title: '多行文本', value: 'textarea' },
         { title: '下拉框', value: 'list' },
         { title: 'popup弹出框', value: 'popup' },
         { title: '图片', value: 'image' },
         { title: 'UE编辑器', value: 'umeditor' },
         { title: '树控件', value: 'tree' }
         normal: 'normal',
         input: 'input',
         inputNumber: 'inputNumber',
         checkbox: 'checkbox',
         select: 'select',
         date: 'date',
         datetime: 'datetime'
         { title: 'String', value: 'string' },
         { title: 'Integer', value: 'int' },
         { title: 'Double', value: 'double' },
         { title: 'Date', value: 'Date' },
         { title: 'BigDecimal', value: 'BigDecimal' },
         { title: 'Text', value: 'Text' },
         { title: 'Blob', value: 'Blob' }
         */
    }

    /**
     * 拼装查询动态列表数据的 SQL（WHERE 之前的部分）
     * <ul>根据配置的列只查询对应的列</ul>
     *
     * @param tableName               - 数据库表名
     * @param tableFieldList          - 数据库表字段信息
     * @param structuredQueryLanguage - SQL
     * @return SELECT tableFieldList FROM tableName
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/20 10:30
     */
    public static void getAutoListBaseStructuredQueryLanguage(final String tableName, List<TableFields> tableFieldList, StringBuffer structuredQueryLanguage) {
        if (tableFieldList == null || tableFieldList.size() == 0) {
            structuredQueryLanguage.append(DataBaseConstant.SQL_SELECT + DataBaseConstant.P_KEY);
        } else {
            structuredQueryLanguage.append(DataBaseConstant.SQL_SELECT);
            int size = tableFieldList.size();
            boolean has = false;
            for (int i = 0; i < size; i++) {
                TableFields item = tableFieldList.get(i);
                if (DataBaseConstant.P_KEY.equals(item.getFieldName())) {
                    has = true;
                }
                // Online配置字典分类树控件报错，逻辑未处理字段文本为空情况
                if (ControlTypeConstant.DICT_TREE.equals(item.getFieldShowType()) && ConvertUtils.isNotEmpty(item.getDictText())) {
                    structuredQueryLanguage.append(item.getDictText()).append(DataBaseConstant.COMMA);
                }
                if (i == size - 1) {
                    structuredQueryLanguage.append(item.getFieldName()).append(DataBaseConstant.SPACE);
                } else {
                    structuredQueryLanguage.append(item.getFieldName()).append(DataBaseConstant.COMMA);
                }
            }
            if (!has) {
                structuredQueryLanguage.append(DataBaseConstant.COMMA + DataBaseConstant.P_KEY);
            }
        }
        structuredQueryLanguage.append(DataBaseConstant.SQL_FROM).append(getRealTableName(tableName));
    }

    /**
     * 拼装条件（数据权限）SQL
     *
     * @param tableFieldList - 数据库表字段信息
     * @param requestParams  - 前端传过来的查询条件
     * @return String - AND A1=1 AND A2=2 ... AND An = n
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/20 10:30
     */
    public static String getAutoListConditionStructuredQueryLanguage(List<TableFields> tableFieldList, Map<String, Object> requestParams) {
        // 条件SQL（数据权限）
        StringBuffer structuredQueryLanguage = new StringBuffer();
        String dataBase = getDataBaseType();
        // 获取数据权限规则
        Map<String, DataPermissionRuleModel> dataPermissionRuleHashMap = QueryGenerator.getDataPermissionRuleHashMap();
        // 权限规则自定义SQL表达式
        for (String rule : dataPermissionRuleHashMap.keySet()) {
            if (ConvertUtils.isNotEmpty(rule) && rule.startsWith(QueryGenerator.SQL_RULES_COLUMN)) {
                structuredQueryLanguage.append(DataBaseConstant.SQL_AND).append(DataBaseConstant.LEFT_BRACKET).append(QueryGenerator.getStructuredQueryLanguageRuleValue(dataPermissionRuleHashMap.get(rule).getRuleValue())).append(DataBaseConstant.RIGHT_BRACKET);
            }
        }
        for (TableFields item : tableFieldList) {
            // 字段名字
            String fieldName = item.getFieldName();
            // 数据库字段类型
            String fieldType = item.getFieldType();
            // 权限查询 兼容下划线和驼峰命名
            if (dataPermissionRuleHashMap.containsKey(fieldName)) {
                addRuleToStringBuffer(dataBase, dataPermissionRuleHashMap.get(fieldName), fieldName, fieldType, structuredQueryLanguage);
            }
            // 驼峰命名
            if (dataPermissionRuleHashMap.containsKey(ConvertUtils.camelNames(fieldName))) {
                addRuleToStringBuffer(dataBase, dataPermissionRuleHashMap.get(fieldName), fieldName, fieldType, structuredQueryLanguage);
            }
            // 如果是外键字段 需要设置为可查询的
            if (ConvertUtils.isNotEmpty(item.getMainField()) && ConvertUtils.isNotEmpty(item.getMainTable())) {
                item.setIsQuery(CommonConstant.INTEGER_YES);
                item.setQueryMode(DataBaseConstant.QUERY_MODE_SINGLE);
            }
            // TODO 此处逻辑存在缺陷，如果页面的字段未配置查询条件，则无法通过此字段进行数据筛选，比如通过 deleteFlag 字段（for: 想用js增强实现条件查询，不成功）
            // 1.判断是否查询
            if (CommonConstant.INTEGER_YES.equals(item.getIsQuery())) {
                // 是否 Oracle 日期类型
                final boolean isOracleDateType = DataBaseConstant.DB_TYPE_ORACLE.equals(dataBase) && fieldType.toLowerCase().contains(DataBaseConstant.DATE_);
                // 2.判断是否是简单查询
                if (DataBaseConstant.QUERY_MODE_SINGLE.equals(item.getQueryMode())) {
                    Object value = requestParams.get(fieldName);
                    if (value != null) {
                        if (isOracleDateType) {
                            structuredQueryLanguage.append(DataBaseConstant.SQL_AND).append(fieldName).append(DataBaseConstant.EQUALS).append(getOracleToDateTimeString(value.toString()));
                        } else {
                            // 是否字符串类型
                            boolean isString = !OnlineDataBaseHandler.isNumberField(fieldType);
                            String fieldCondition = QueryGenerator.getSingleQueryConditionStructuredQueryLanguage(fieldName, DataBaseConstant.EMPTY, value, isString);
                            structuredQueryLanguage.append(DataBaseConstant.SQL_AND).append(fieldCondition);
                        }
                    }
                } else {
                    // 范围查询走此逻辑
                    Object valueBegin = requestParams.get(fieldName + DataBaseConstant.SUFFIX_START);
                    if (valueBegin != null) {
                        structuredQueryLanguage.append(DataBaseConstant.SQL_AND).append(fieldName).append(DataBaseConstant.GREATER_THAN_OR_EQUAL_TO);
                        if (OnlineDataBaseHandler.isNumberField(fieldType)) {
                            // 如果数字类型直接拼在 SQL 后面
                            structuredQueryLanguage.append(valueBegin.toString());
                        } else if (isOracleDateType) {
                            structuredQueryLanguage.append(getOracleToDateTimeString(valueBegin.toString()));
                        } else {
                            // 如果字符串类型需要加单引号
                            structuredQueryLanguage.append(DataBaseConstant.SINGLE_QUOTE).append(valueBegin.toString()).append(DataBaseConstant.SINGLE_QUOTE);
                        }
                    }
                    Object valueEnd = requestParams.get(fieldName + DataBaseConstant.SUFFIX_END);
                    if (valueEnd != null) {
                        structuredQueryLanguage.append(DataBaseConstant.SQL_AND).append(fieldName).append(DataBaseConstant.LESS_THAN_OR_EQUAL_TO);
                        if (OnlineDataBaseHandler.isNumberField(fieldType)) {
                            structuredQueryLanguage.append(valueEnd.toString());
                        } else if (isOracleDateType) {
                            structuredQueryLanguage.append(getOracleToDateTimeString(valueEnd.toString()));
                        } else {
                            structuredQueryLanguage.append(DataBaseConstant.SINGLE_QUOTE).append(valueEnd.toString()).append(DataBaseConstant.SINGLE_QUOTE);
                        }
                    }
                }
            }
        }
        return structuredQueryLanguage.toString();
    }

    /**
     * ORACLE 处理时间类型的字段需要特殊处理一下
     *
     * @param value - 字符串时间
     * @return String - 处理时间
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/20 10:30
     */
    public static String getOracleToDateTimeString(final String value) {
        return " to_date('" + value + "', 'yyyy-MM-dd HH24:mi:ss') ";
    }

    /**
     * ORACLE 处理时间类型的字段需要特殊处理一下
     *
     * @param value - 字符串时间
     * @return String - 处理时间
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/20 10:30
     */
    public static String getOracleToDateString(final String value) {
        return " to_date('" + value + "', 'yyyy-MM-dd') ";
    }

    /**
     * 获取高级查询条件 SQL，支持主子表查询
     *
     * @param requestParams - 前端传过来的查询条件
     * @return String - AND A1=1 AND A2=2 ... AND An = n
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/20 10:30
     */
    public static String getAutoListSuperQueryStructuredQueryLanguage(Map<String, Object> requestParams) {
        // 取出查询条件
        Object superQueryParamsObject = requestParams.get(DataBaseConstant.SUPER_QUERY_PARAMS);
        if (superQueryParamsObject == null || StringUtils.isBlank(superQueryParamsObject.toString())) {
            return DataBaseConstant.EMPTY;
        }
        ITableFieldsService service = SpringContextUtils.getBean(ITableFieldsService.class);
        // 校验 ITableFieldsService 是否获取成功
        ArgumentResponseEnum.NULL_POINTER_EXCEPTION.assertNotNull(service);
        String superQueryParams;
        try {
            superQueryParams = URLDecoder.decode(superQueryParamsObject.toString(), DataBaseConstant.UTF_8);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return DataBaseConstant.EMPTY;
        }
        JSONArray params = JSONArray.parseArray(superQueryParams);
        // 取出 matchType
        Object superQueryMatchTypeObject = requestParams.get(DataBaseConstant.SUPER_QUERY_MATCH_TYPE);
        MatchTypeEnum matchType = MatchTypeEnum.getByValue(superQueryMatchTypeObject);
        if (matchType == null) {
            matchType = MatchTypeEnum.AND;
        }
        // 子表 map
        Map<String, JSONObject> subTablesForeignKeyMap = new HashMap<>(16);
        // 遍历查询条件，并拼接SQL
        StringBuilder builder = new StringBuilder(DataBaseConstant.SQL_AND).append(DataBaseConstant.LEFT_BRACKET);
        for (int i = 0; i < params.size(); i++) {
            JSONObject parameter = params.getJSONObject(i);
            String field = parameter.getString("field");
            String[] fieldArray = field.split(DataBaseConstant.COMMA);
            // 没有使用逗号分割，说明是主表
            if (fieldArray.length == 1) {
                spliceSuperQueryField(builder, field, parameter, matchType, null, i == 0);
            } else if (fieldArray.length == 2) {
                // 使用了逗号分割，是子表，index 0 = 子表名， index 1 = 子表字段
                String childTableName = fieldArray[0];
                String subFieldName = fieldArray[1];
                JSONObject childTable = subTablesForeignKeyMap.get(childTableName);
                if (childTable == null) {
                    List<TableFields> subTableFields = service.queryTableFieldListByTableName(childTableName);
                    childTable = new JSONObject(3);
                    for (TableFields tableFields : subTableFields) {
                        if (StringUtils.isNotBlank(tableFields.getMainTable())) {
                            childTable.put(DataBaseConstant.CHILD_TABLE_NAME, childTableName);
                            childTable.put(DataBaseConstant.CHILD_TABLE_FIELD, tableFields.getFieldName());
                            childTable.put(DataBaseConstant.MAIN_TABLE_NAME, tableFields.getMainTable());
                            childTable.put(DataBaseConstant.MAIN_TABLE_FIELD, tableFields.getMainField());
                        }
                    }
                    subTablesForeignKeyMap.put(childTableName, childTable);
                }
                spliceSuperQueryField(builder, subFieldName, parameter, matchType, childTable, i == 0);
            }
        }
        return builder.append(DataBaseConstant.RIGHT_BRACKET).toString();
    }

    /**
     * Map 的 key 转成小写
     *
     * @param stringObjectMap - 源 - MAP
     * @return Map<String, Object> - Map
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/23 11:21
     */
    public static Map<String, Object> transLowerCaseMapKey(Map<String, Object> stringObjectMap) {
        Map<String, Object> resultMap = new HashMap<>(16);
        if (stringObjectMap == null || stringObjectMap.isEmpty()) {
            return resultMap;
        }
        for (Map.Entry<String, Object> entry : stringObjectMap.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value instanceof Clob) {
                value = clobToString((Clob) value);
            } else if (value instanceof byte[]) {
                value = new String((byte[]) value);
            } else if (value instanceof Blob) {
                try {
                    Blob blob = (Blob) value;
                    value = new String(blob.getBytes(1, (int) blob.length()), StandardCharsets.UTF_8);
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            }
            String toLowerCaseKey = key.toLowerCase();
            resultMap.put(toLowerCaseKey, value);
        }
        return resultMap;
    }

    /**
     * 将所有 Map 的 key 转成小写
     *
     * @param mapList - 源
     * @return List<Map < String, Object>>
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/23 11:21
     */
    public static List<Map<String, Object>> toLowerCasePageList(List<Map<String, Object>> mapList) {
        List<Map<String, Object>> mapArrayList = new ArrayList<>();
        for (Map<String, Object> row : mapList) {
            Map<String, Object> resultMap = transLowerCaseMapKey(row);
            mapArrayList.add(resultMap);
        }
        return mapArrayList;
    }

    /**
     * 将 JSON 的 key 转成小写
     *
     * @param json - JSONObject
     * @return JSONObject - 转换后的
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/23 11:21
     */
    public static JSONObject transLowerCaseMapKey(JSONObject json) {
        if (DataBaseTableUtil.hasLetterCaseProblem()) {
            JSONObject resultJson = new JSONObject();
            if (json == null || json.isEmpty()) {
                return resultJson;
            }
            Set<String> keySet = json.keySet();
            for (String key : keySet) {
                String newKey = key.toLowerCase();
                resultJson.put(newKey, json.get(key));
            }
            return resultJson;
        } else {
            return json;
        }
    }

    /**
     * 获取真实数据库表表名
     *
     * @param tableName - 数据库表表名
     * @return String - 真实数据库表表名
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/23 13:50
     */
    public static String getRealTableName(String tableName) {
        if (Pattern.matches("^[a-zA-z].*\\$\\d+$", tableName)) {
            // 说明是复制表
            return tableName.substring(0, tableName.lastIndexOf(DataBaseConstant.DOLLAR));
        }
        return tableName;
    }

    /**
     * 表单设计器获取动态 SQL 用于保存表单数据
     *
     * @param tableName      - 数据库表表名
     * @param tableFieldList - 数据库表字段信息
     * @param requestJson    - 表单数据
     * @return List<Map < String, Object>>
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/23 11:21
     */
    public static Map<String, Object> getCrazyFormDataSaveStructuredQueryLanguage(final String tableName, List<TableFields> tableFieldList, JSONObject requestJson) {
        // 表单数据
        Map<String, Object> params = new HashMap<>(16);
        String dataBase = getDataBaseType();
        // INSERT_INTO 语句的字段
        StringBuilder insertIntoField = new StringBuilder();
        // INSERT_INTO 语句的内容
        StringBuilder insertIntoValue = new StringBuilder();
        // 是否有主键字段
        boolean hasKey = Boolean.FALSE;
        // 主键字段值
        String keyFieldValue = null;
        // 数据库表字段信息
        for (TableFields tableFields : tableFieldList) {
            String key = tableFields.getFieldName();
            if (null == key) {
                log.info("保存表单数据遇见空名称的字段" + tableFields.getId());
                continue;
            }
            // 为空且不为标准字段则不入库
            if (requestJson.get(key) == null && !(DataBaseConstant.CREATE_BY_FIELD.equalsIgnoreCase(key) || DataBaseConstant.CREATE_TIME_FIELD.equalsIgnoreCase(key) || DataBaseConstant.ORGANIZATION_CODE_FIELD.equalsIgnoreCase(key))) {
                continue;
            }
            // 赋值系统默认字段
            initSystemFiles(tableFields, requestJson, DataBaseConstant.CREATE_BY_FIELD, DataBaseConstant.CREATE_TIME_FIELD, DataBaseConstant.ORGANIZATION_CODE_FIELD);
            // 数值、时间类型 值为空不更改
            if (DataBaseConstant.EMPTY.equals(requestJson.get(key))) {
                String fieldType = tableFields.getFieldType();
                if (OnlineDataBaseHandler.isNumberField(fieldType) || OnlineDataBaseHandler.isDateField(fieldType)) {
                    continue;
                }
            }
            // 主键字段相关
            if (DataBaseConstant.P_KEY.equalsIgnoreCase(key)) {
                hasKey = true;
                keyFieldValue = requestJson.getString(key);
                continue;
            }
            // 拼接 INSERT INTO (这里面的东西) VALUES (......)
            insertIntoField.append(DataBaseConstant.COMMA).append(key);
            // 拼接 INSERT INTO (......) VALUES (这里面的东西)
            String value = OnlineDataBaseHandler.initMybatisValueWithJdbcType(dataBase, tableFields, requestJson, params);
            insertIntoValue.append(DataBaseConstant.COMMA).append(value);
        }
        if (!hasKey || ConvertUtils.isEmpty(keyFieldValue)) {
            keyFieldValue = String.valueOf(IdWorker.getId());
        }
        StringBuilder structuredQueryLanguage = new StringBuilder().append(DataBaseConstant.SQL_INSERT_INTO).append(getRealTableName(tableName))
                .append(DataBaseConstant.LEFT_BRACKET).append(DataBaseConstant.P_KEY).append(insertIntoField).append(DataBaseConstant.RIGHT_BRACKET)
                .append(DataBaseConstant.SQL_VALUES).append(DataBaseConstant.LEFT_BRACKET)
                .append(DataBaseConstant.SINGLE_QUOTE).append(keyFieldValue).append(DataBaseConstant.SINGLE_QUOTE).append(insertIntoValue)
                .append(DataBaseConstant.RIGHT_BRACKET);
        params.put("execute_structured_query_language_string", structuredQueryLanguage.toString());
        log.info("-- 表单设计器表单保存 StructuredQueryLanguage -->" + structuredQueryLanguage.toString());
        return params;
    }

    /**
     * 表单数据保存 SQL 获取（默认id是主键并且为 IdWorker）
     *
     * @param tableName      - 数据库表表名
     * @param tableFieldList - 数据库表字段信息
     * @param requestJson    - 表单数据
     * @return List<Map < String, Object>>
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/23 11:21
     */
    public static Map<String, Object> getFormDataSaveStructuredQueryLanguage(final String tableName, List<TableFields> tableFieldList, JSONObject requestJson) {
        // 表单数据
        Map<String, Object> params = new HashMap<>(16);
        String dataBase = getDataBaseType();
        // INSERT_INTO 语句的字段
        StringBuilder insertIntoField = new StringBuilder();
        // INSERT_INTO 语句的内容
        StringBuilder insertIntoValue = new StringBuilder();
        // 是否有主键字段
        boolean hasKey = Boolean.FALSE;
        // 主键字段值
        String keyFieldValue = null;
        // 必要字段获取
        Set<String> needFields = getNeedHandleField(tableFieldList);
        // 数据库表字段信息 注意 ：此处循环内部代码 会改变原始集合中对象的属性值 如果持久层是 Hibernate 需要手动 new 一个新的
        for (TableFields tableFields : tableFieldList) {
            String key = tableFields.getFieldName();
            if (null == key) {
                log.info("保存表单数据遇见空名称的字段" + tableFields.getId());
                continue;
            }
            // 设置 流程状态 的默认值 1：待提交   process_state
            if (DataBaseConstant.PROCESS_STATE_FIELD.equalsIgnoreCase(key)) {
                insertIntoField.append(DataBaseConstant.COMMA).append(key);
                insertIntoValue.append(DataBaseConstant.COMMA).append(DataBaseConstant.SINGLE_QUOTE).append(DataBaseConstant.ONE).append(DataBaseConstant.SINGLE_QUOTE);
                continue;
            }
            // 处理必要字段
            if (needFields.contains(key)) {
                // 拼接 INSERT INTO (这里面的东西) VALUES (......)
                insertIntoField.append(DataBaseConstant.COMMA).append(key);
                // 拼接 INSERT INTO (......) VALUES (这里面的东西)
                String value = OnlineDataBaseHandler.initMybatisValueWithJdbcType(dataBase, tableFields, requestJson, params);
                insertIntoValue.append(DataBaseConstant.COMMA).append(value);
                continue;
            }
            // 不显示且非外键不入库 且数据库没有设置默认值
            if (CommonConstant.INTEGER_NO.equals(tableFields.getIsShowForm()) && ConvertUtils.isEmpty(tableFields.getMainField())) {
                if (ConvertUtils.isEmpty(tableFields.getFieldDefaultValue())) {
                    continue;
                }
            }
            // 为空不入库 如果有默认值则设置默认值
            if (requestJson.get(key) == null) {
                if (ConvertUtils.isEmpty(tableFields.getFieldDefaultValue())) {
                    continue;
                } else {
                    requestJson.put(key, tableFields.getFieldDefaultValue());
                }
            }
            // 赋值系统默认字段
            initSystemFiles(tableFields, requestJson, DataBaseConstant.CREATE_BY_FIELD, DataBaseConstant.CREATE_TIME_FIELD, DataBaseConstant.ORGANIZATION_CODE_FIELD);
            // 数值、时间类型 值为空不更改
            if (DataBaseConstant.EMPTY.equals(requestJson.get(key))) {
                String fieldType = tableFields.getFieldType();
                if (OnlineDataBaseHandler.isNumberField(fieldType) || OnlineDataBaseHandler.isDateField(fieldType)) {
                    continue;
                }
            }
            // 主键字段相关
            if (DataBaseConstant.P_KEY.equalsIgnoreCase(key)) {
                hasKey = Boolean.TRUE;
                keyFieldValue = requestJson.getString(key);
                continue;
            }
            // 拼接 INSERT INTO (这里面的东西) VALUES (......)
            insertIntoField.append(DataBaseConstant.COMMA).append(key);
            // 拼接 INSERT INTO (......) VALUES (这里面的东西)
            String value = OnlineDataBaseHandler.initMybatisValueWithJdbcType(dataBase, tableFields, requestJson, params);
            insertIntoValue.append(DataBaseConstant.COMMA).append(value);
        }
        // 确定主键值
        if (hasKey) {
            if (ConvertUtils.isEmpty(keyFieldValue)) {
                keyFieldValue = String.valueOf(IdWorker.getId());
            }
        } else {
            keyFieldValue = String.valueOf(IdWorker.getId());
        }
        StringBuilder structuredQueryLanguage = new StringBuilder().append(DataBaseConstant.SQL_INSERT_INTO).append(getRealTableName(tableName))
                .append(DataBaseConstant.LEFT_BRACKET).append(DataBaseConstant.P_KEY).append(insertIntoField).append(DataBaseConstant.RIGHT_BRACKET)
                .append(DataBaseConstant.SQL_VALUES).append(DataBaseConstant.LEFT_BRACKET)
                .append(DataBaseConstant.SINGLE_QUOTE).append(keyFieldValue).append(DataBaseConstant.SINGLE_QUOTE).append(insertIntoValue)
                .append(DataBaseConstant.RIGHT_BRACKET);
        params.put("execute_structured_query_language_string", structuredQueryLanguage.toString());
        log.info("-- 动态表单保存 StructuredQueryLanguage -->" + structuredQueryLanguage.toString());
        return params;
    }

    /**
     * 表单设计器获取动态 SQL 用于编辑表单数据
     *
     * @param tableName      - 数据库表表名
     * @param tableFieldList - 数据库表字段信息
     * @param requestJson    - 表单数据
     * @return List<Map < String, Object>>
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/23 11:21
     */
    public static Map<String, Object> getCrazyFormDataEditStructuredQueryLanguage(final String tableName, List<TableFields> tableFieldList, JSONObject requestJson) {
        // 表单数据
        Map<String, Object> params = new HashMap<>(16);
        String dataBase = getDataBaseType();
        // UPDATE 语句的 SET 内容
        StringBuilder updateSetValue = new StringBuilder();
        // 数据库表字段信息
        for (TableFields tableFields : tableFieldList) {
            String key = tableFields.getFieldName();
            if (null == key) {
                log.info("保存表单数据遇见空名称的字段" + tableFields.getId());
                continue;
            }
            // 主键不能更改
            if (DataBaseConstant.P_KEY.equals(key)) {
                continue;
            }
            // 为空且不为标准字段则不入库
            if (requestJson.get(key) == null && !(DataBaseConstant.UPDATE_BY_FIELD.equalsIgnoreCase(key) || DataBaseConstant.UPDATE_TIME_FIELD.equalsIgnoreCase(key) || DataBaseConstant.ORGANIZATION_CODE_FIELD.equalsIgnoreCase(key))) {
                continue;
            }
            // 赋值系统默认字段
            initSystemFiles(tableFields, requestJson, DataBaseConstant.UPDATE_BY_FIELD, DataBaseConstant.UPDATE_TIME_FIELD, DataBaseConstant.ORGANIZATION_CODE_FIELD);
            // 数值、时间类型 值为空不更改
            if (DataBaseConstant.EMPTY.equals(requestJson.get(key))) {
                String fieldType = tableFields.getFieldType();
                if (OnlineDataBaseHandler.isNumberField(fieldType) || OnlineDataBaseHandler.isDateField(fieldType)) {
                    continue;
                }
            }
            String setValue = OnlineDataBaseHandler.initMybatisValueWithJdbcType(dataBase, tableFields, requestJson, params);
            updateSetValue.append(key).append(DataBaseConstant.EQUALS).append(setValue).append(DataBaseConstant.COMMA);
        }
        // UPDATE 语句的 SET 内容 调整
        String setValue = updateSetValue.toString();
        if (setValue.endsWith(DataBaseConstant.COMMA)) {
            setValue = setValue.substring(0, setValue.length() - 1);
        }
        StringBuilder structuredQueryLanguage = new StringBuilder()
                .append(DataBaseConstant.SQL_UPDATE).append(getRealTableName(tableName))
                .append(DataBaseConstant.SQL_SET).append(setValue)
                .append(DataBaseConstant.SQL_WHERE).append(DataBaseConstant.P_KEY).append(DataBaseConstant.EQUALS).append(DataBaseConstant.SINGLE_QUOTE).append(requestJson.getString(DataBaseConstant.P_KEY)).append(DataBaseConstant.SINGLE_QUOTE);
        params.put("execute_structured_query_language_string", structuredQueryLanguage.toString());
        log.info("-- 表单设计器表单编辑 StructuredQueryLanguage -->" + structuredQueryLanguage.toString());
        return params;
    }

    /**
     * 表单数据修改 SQL 获取（默认id是主键并且为 IdWorker）
     *
     * @param tableName      - 数据库表表名
     * @param tableFieldList - 数据库表字段信息
     * @param requestJson    - 表单数据
     * @return List<Map < String, Object>>
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/23 11:21
     */
    public static Map<String, Object> getFormDataEditStructuredQueryLanguage(final String tableName, List<TableFields> tableFieldList, JSONObject requestJson) {
        // 表单数据
        Map<String, Object> params = new HashMap<>(16);
        String dataBase = getDataBaseType();
        // UPDATE 语句的 SET 内容
        StringBuilder updateSetValue = new StringBuilder();
        //获取必要字段
        Set<String> needFields = getNeedHandleField(tableFieldList);
        // 数据库表字段信息（注意 暂时只能修改界面上显示的数据）
        for (TableFields tableFields : tableFieldList) {
            String key = tableFields.getFieldName();
            if (null == key) {
                log.info("保存表单数据遇见空名称的字段" + tableFields.getId());
                continue;
            }
            // 处理必要字段
            if (needFields.contains(key)) {
                // 拼接 UPDATE TABLE SET (这里面的东西) WHERE (......)
                if (requestJson.get(key) != null && !DataBaseConstant.EMPTY.equals(requestJson.getString(key))) {
                    String sqlValue = OnlineDataBaseHandler.initMybatisValueWithJdbcType(dataBase, tableFields, requestJson, params);
                    updateSetValue.append(key).append(DataBaseConstant.SINGLE_QUOTE).append(sqlValue).append(DataBaseConstant.COMMA);
                    continue;
                }
            }
            // 不显示不改
            if (CommonConstant.INTEGER_NO.equals(tableFields.getIsShowForm())) {
                continue;
            }
            // 主键不能更改
            if (DataBaseConstant.P_KEY.equals(key)) {
                continue;
            }
            // 为空且不为标准字段则不入库
            // if (requestJson.get(key) == null && !(DataBaseConstant.UPDATE_BY_FIELD.equalsIgnoreCase(key) || DataBaseConstant.UPDATE_TIME_FIELD.equalsIgnoreCase(key) || DataBaseConstant.ORGANIZATION_CODE_FIELD.equalsIgnoreCase(key))) {
            //     continue;
            // }
            // 赋值系统默认字段
            initSystemFiles(tableFields, requestJson, DataBaseConstant.UPDATE_BY_FIELD, DataBaseConstant.UPDATE_TIME_FIELD, DataBaseConstant.ORGANIZATION_CODE_FIELD);
            // 数值、时间类型 值为空不更改
            if (DataBaseConstant.EMPTY.equals(requestJson.get(key))) {
                String fieldType = tableFields.getFieldType();
                if (OnlineDataBaseHandler.isNumberField(fieldType) || OnlineDataBaseHandler.isDateField(fieldType)) {
                    continue;
                }
            }
            String setValue = OnlineDataBaseHandler.initMybatisValueWithJdbcType(dataBase, tableFields, requestJson, params);
            updateSetValue.append(key).append(DataBaseConstant.EQUALS).append(setValue).append(DataBaseConstant.COMMA);
        }
        // UPDATE 语句的 SET 内容 调整
        String setValue = updateSetValue.toString();
        if (setValue.endsWith(DataBaseConstant.COMMA)) {
            setValue = setValue.substring(0, setValue.length() - 1);
        }
        StringBuilder structuredQueryLanguage = new StringBuilder()
                .append(DataBaseConstant.SQL_UPDATE).append(getRealTableName(tableName))
                .append(DataBaseConstant.SQL_SET).append(setValue)
                .append(DataBaseConstant.SQL_WHERE).append(DataBaseConstant.P_KEY).append(DataBaseConstant.EQUALS).append(DataBaseConstant.SINGLE_QUOTE).append(requestJson.getString(DataBaseConstant.P_KEY)).append(DataBaseConstant.SINGLE_QUOTE);
        params.put("execute_structured_query_language_string", structuredQueryLanguage.toString());
        log.info("-- 动态表单编辑 StructuredQueryLanguage -->" + structuredQueryLanguage.toString());
        return params;
    }

    /**
     * 设置树节点无子节点状态（如果当前节点原本有子节点 现在木有了，更新状态）
     *
     * @param tableName - 数据库表表名
     * @param filed     - 有无子节点标识字段
     * @param id        - 主键值
     * @return null -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/23 17:14
     */
    public static Map<String, Object> getTreeNodeNoChildNodeStructuredQueryLanguage(final String tableName, String filed, final String id) {
        Map<String, Object> params = new HashMap<>(1);
        StringBuilder structuredQueryLanguage = new StringBuilder()
                .append(DataBaseConstant.SQL_UPDATE).append(getRealTableName(tableName))
                .append(DataBaseConstant.SQL_SET).append(filed).append(DataBaseConstant.EQUALS).append(DataBaseConstant.ZERO)
                .append(DataBaseConstant.SQL_WHERE).append(DataBaseConstant.P_KEY).append(DataBaseConstant.EQUALS).append(DataBaseConstant.SINGLE_QUOTE).append(id).append(DataBaseConstant.SINGLE_QUOTE);
        params.put("execute_structured_query_language_string", structuredQueryLanguage.toString());
        log.info("-- 修改树节点状态：为无子节点 StructuredQueryLanguage -->" + structuredQueryLanguage.toString());
        return params;
    }

    /**
     * 根据 ID 查询表单数据 SQL 获取
     *
     * @param tableName      - 数据库表表名
     * @param tableFieldList - 数据库表字段信息
     * @param id             - 表单数据
     * @return String - StructuredQueryLanguage
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/23 11:21
     */
    public static String getQueryFormDataByIdStructuredQueryLanguage(final String tableName, List<TableFields> tableFieldList, final String id) {
        return getQueryFormDataByParameterStructuredQueryLanguage(tableName, tableFieldList, DataBaseConstant.P_KEY, id);
    }

    /**
     * 组装查询SQL
     *
     * @param tableName      - 表名
     * @param tableFieldList - 需要查询的字段集合
     * @param linkField      - 查询条件字段
     * @param value          - 查询条件值
     * @return String - StructuredQueryLanguage
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/23 11:21
     */
    public static String getQueryFormDataByParameterStructuredQueryLanguage(final String tableName, List<TableFields> tableFieldList, final String linkField, final String value) {
        StringBuilder structuredQueryLanguage = new StringBuilder().append(DataBaseConstant.SQL_SELECT);
        int size = tableFieldList.size();
        // 是否有主键字段
        boolean hasKey = Boolean.FALSE;
        for (int i = 0; i < size; i++) {
            String key = tableFieldList.get(i).getFieldName();
            if (DataBaseConstant.P_KEY.equals(key)) {
                // 主键字段
                hasKey = true;
            }
            // 其他字段
            structuredQueryLanguage.append(key);
            if (size > i + 1) {
                // 防止做后一个字段后面加 “,”
                structuredQueryLanguage.append(DataBaseConstant.COMMA);
            }
        }
        if (!hasKey) {
            // 将 ID 也返回给前端
            structuredQueryLanguage.append(DataBaseConstant.COMMA).append(DataBaseConstant.P_KEY);
        }
        structuredQueryLanguage.append(DataBaseConstant.SQL_FROM).append(getRealTableName(tableName)).append(DataBaseConstant.SQL_WHERE_TRUE)
                .append(DataBaseConstant.SQL_AND).append(linkField).append(DataBaseConstant.EQUALS).append(DataBaseConstant.SINGLE_QUOTE).append(value).append(DataBaseConstant.SINGLE_QUOTE);
        return structuredQueryLanguage.toString();
    }

    /**
     * SQL 值替换 SQL 增强用于替换 SQL 中的变量用 格式化
     *
     * @param structuredQueryLanguage - 原SQL
     * @param requestJson             - 表单数据
     * @return String - 可执行SQL
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/24 8:50
     */
    public static String formatStructuredQueryLanguage(String structuredQueryLanguage, JSONObject requestJson) {
        if (requestJson == null) {
            return structuredQueryLanguage;
        }
        // 处理主键参数
        structuredQueryLanguage = structuredQueryLanguage.replace("#{ID}", String.valueOf(IdWorker.getId()));
        Set<String> paramsHashSet = QueryGenerator.getStructuredQueryLanguageRuleParams(structuredQueryLanguage);
        // 格式化其他参数
        for (String key : paramsHashSet) {
            if (requestJson.get(key.toUpperCase()) == null && requestJson.get(key.toLowerCase()) == null) {
                String tempValue = QueryGenerator.convertRuleValue(key);
                structuredQueryLanguage = structuredQueryLanguage.replace("#{" + key + "}", tempValue);
            } else {
                String jsonValue = DataBaseConstant.EMPTY;
                if (requestJson.containsKey(key.toLowerCase())) {
                    // 全小写获取
                    jsonValue = requestJson.getString(key.toLowerCase());
                } else if (requestJson.containsKey(key.toUpperCase())) {
                    // 全大写获取
                    jsonValue = requestJson.getString(key.toUpperCase());
                }
                structuredQueryLanguage = structuredQueryLanguage.replace("#{" + key + "}", jsonValue);
            }
        }
        return structuredQueryLanguage;
    }

    /**
     * 根据字段集合组装 JSON schema
     *
     * @param tableFieldList        - 有效的数据库表字段信息
     * @param disabledFieldNameList - 被禁用的列名称
     * @param treeColumn            - 树形列表用到 表示被展示为树形下拉的列
     * @return JSONObject - JsonSchema
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/24 8:50
     */
    public static JSONObject getJsonSchemaByTableFieldList(List<TableFields> tableFieldList, List<String> disabledFieldNameList, TreeSelectColumn treeColumn) {
        // 必填字段
        List<String> requiredArrayList = new ArrayList<>();
        // 公共属性
        List<BaseCommonProperty> propertyArrayList = new ArrayList<>();
        // 需要排除字段，级联下拉，已经加载的不再加载
        List<String> excludeFields = new ArrayList<>();
        // 数据库表字段信息
        for (TableFields tableFields : tableFieldList) {
            // 字段名字
            String field = tableFields.getFieldName();
            // 主键、被排除字段
            if (DataBaseConstant.P_KEY.equals(field) || excludeFields.contains(field)) {
                continue;
            }
            // 1.获取 requiredArrayList（必填字段）
            if (CommonConstant.INTEGER_YES.equals(tableFields.getFieldMustInput())) {
                requiredArrayList.add(field);
            }
            // 表单控件类型
            String filedShowType = tableFields.getFieldShowType();
            // 字段备注
            String title = tableFields.getFieldTxt();
            // 2.确定字段控件类型展示属性信息
            BaseCommonProperty baseCommonProperty;
            // 下拉字段设置为数字类型，控件出不来
            if (ControlTypeConstant.SWITCH.equals(filedShowType)) {
                // 控件类型 - 开关
                baseCommonProperty = new SwitchPropertyBase(field, title, tableFields.getFieldExtendJson());
            } else if (hasDictConfig(filedShowType)) {
                // 列表类型
                List<DictVO> include = queryDictFieldOptions(tableFields);
                baseCommonProperty = new StringPropertyBase(field, title, filedShowType, tableFields.getFieldLength(), include);
                if (OnlineDataBaseHandler.isNumberField(tableFields.getFieldType())) {
                    baseCommonProperty.setType(DataBaseConstant.NUMBER);
                }
            } else if (OnlineDataBaseHandler.isNumberField(tableFields.getFieldType())) {
                // 数字类型
                NumberPropertyBase numberProperty = new NumberPropertyBase(field, title, DataBaseConstant.NUMBER);
                if (FormValidPatternEnum.INTEGER.getType().equals(tableFields.getFieldValidType())) {
                    numberProperty.setPattern(FormValidPatternEnum.INTEGER.getPattern());
                }
                baseCommonProperty = numberProperty;
            } else {
                switch (filedShowType) {
                    case ControlTypeConstant.POPUP:
                        // POPUP 类型
                        PopupPropertyBase popupProperty = new PopupPropertyBase(field, title, tableFields.getDictTable(), tableFields.getDictText(), tableFields.getDictField());
                        String backFields = tableFields.getDictText();
                        if (backFields != null && !backFields.equals(DataBaseConstant.EMPTY)) {
                            String[] dictTextArray = backFields.split(DataBaseConstant.COMMA);
                            for (String dictText : dictTextArray) {
                                if (existFieldName(dictText, tableFieldList)) {
                                    // 如果现有的列 有此配置的列 跳过
                                    continue;
                                }
                                BaseCommonProperty hiddenProperty = new HiddenPropertyBase(dictText, dictText);
                                hiddenProperty.setOrder(tableFields.getSortOrder());
                                propertyArrayList.add(hiddenProperty);
                            }
                        }
                        baseCommonProperty = popupProperty;
                        break;
                    case ControlTypeConstant.SELECT_SEARCH:
                        // 字典 类型
                        baseCommonProperty = new DictPropertyBase(field, title, tableFields.getDictTable(), tableFields.getDictField(), tableFields.getDictText());
                        break;
                    case ControlTypeConstant.LINK_DOWN:
                        // 级联下拉 类型
                        LinkDownPropertyBase linkDownProperty = new LinkDownPropertyBase(field, title, tableFields.getDictTable());
                        getLinkDownOtherField(linkDownProperty, tableFieldList, excludeFields);
                        baseCommonProperty = linkDownProperty;
                        break;
                    case ControlTypeConstant.SELECT_TREE: {
                        // 树控件
                        String dictText = tableFields.getDictText();
                        String[] cols = dictText.split(DataBaseConstant.COMMA);
                        String dict = tableFields.getDictTable() + DataBaseConstant.COMMA + cols[2] + DataBaseConstant.COMMA + cols[0];
                        TreeSelectPropertyBase treeSelectProperty = new TreeSelectPropertyBase(field, title, dict, cols[1], tableFields.getDictField());
                        if (cols.length > 3) {
                            treeSelectProperty.setHasChildField(cols[3]);
                        }
                        baseCommonProperty = treeSelectProperty;
                        break;
                    }
                    case ControlTypeConstant.DICT_TREE: {
                        // 分类字典配置编码 这块支持无配置加载所有
                        String dictText = tableFields.getDictText();
                        String dictCode = tableFields.getDictField();
                        String parentId = DataBaseConstant.ZERO;
                        if (ConvertUtils.isNotEmpty(dictCode) && !DataBaseConstant.ZERO.equals(dictCode)) {
                            // TODO:This 根据 code 获取对应的 ID
                            TableHeadMapper mapper = SpringContextUtils.getBean(TableHeadMapper.class);
                            // 校验 TableHeadMapper 是否获取成功
                            ArgumentResponseEnum.NULL_POINTER_EXCEPTION.assertNotNull(mapper);
                            // parentId = mapper.queryCategoryIdByCode(dictCode);
                        }
                        if (ConvertUtils.isEmpty(dictText)) {
                            // 分类字典树控件 简易版 只有一个字段
                            baseCommonProperty = new TreeSelectPropertyBase(field, title, parentId);
                        } else {
                            // 需要处理两个字段
                            baseCommonProperty = new TreeSelectPropertyBase(field, title, parentId, dictText);
                            BaseCommonProperty hiddenProperty = new HiddenPropertyBase(dictText, dictText);
                            propertyArrayList.add(hiddenProperty);
                        }
                        break;
                    }
                    default:
                        if (treeColumn != null && field.equals(treeColumn.getFieldName())) {
                            // 树形列表 表单的树控件
                            String dict = treeColumn.getTableName() + DataBaseConstant.COMMA + treeColumn.getTextField() + DataBaseConstant.COMMA + treeColumn.getCodeField();
                            TreeSelectPropertyBase treeSelectProperty = new TreeSelectPropertyBase(field, title, dict, treeColumn.getPidField(), treeColumn.getPidValue());
                            treeSelectProperty.setHasChildField(treeColumn.getHsaChildField());
                            treeSelectProperty.setParentComponent(CommonConstant.INTEGER_YES);
                            baseCommonProperty = treeSelectProperty;
                        } else {
                            StringPropertyBase stringProperty = new StringPropertyBase(field, title, filedShowType, tableFields.getFieldLength());
                            // 主表、单表 表单校验 通过 pattern 实现
                            if (ConvertUtils.isNotEmpty(tableFields.getFieldValidType())) {
                                FormValidPatternEnum patternInfo = FormValidPatternEnum.getPatternInfoByType(tableFields.getFieldValidType());
                                if (patternInfo != null) {
                                    if (FormValidPatternEnum.NOTNULL == patternInfo) {
                                        requiredArrayList.add(field);
                                    } else {
                                        stringProperty.setPattern(patternInfo.getPattern());
                                        stringProperty.setErrorInfo(patternInfo.getMessage());
                                    }
                                } else {
                                    // 不是预设的正则，就视为用户自定义的正则
                                    stringProperty.setPattern(tableFields.getFieldValidType());
                                    stringProperty.setErrorInfo(ValidationMessageConstant.FORMAT_ERR);
                                }
                            }
                            baseCommonProperty = stringProperty;
                        }
                        break;
                }
            }
            // 设置只读字段不可编辑
            if ((CommonConstant.INTEGER_YES.equals(tableFields.getIsReadOnly())) || (disabledFieldNameList != null && disabledFieldNameList.contains(field))) {
                baseCommonProperty.setDisabled(Boolean.TRUE);
            }
            // 排序号
            baseCommonProperty.setOrder(tableFields.getSortOrder());
            // 默认值
            baseCommonProperty.setDefaultValue(tableFields.getFieldDefaultValue());
            propertyArrayList.add(baseCommonProperty);
        }
        // JsonSchema
        JsonSchemaDescription jsonSchemaDescription;
        if (requiredArrayList.size() > 0) {
            jsonSchemaDescription = new JsonSchemaDescription(requiredArrayList);
        } else {
            jsonSchemaDescription = new JsonSchemaDescription();
        }
        return JsonSchemaUtil.getJsonSchema(jsonSchemaDescription, propertyArrayList);
    }

    /**
     * 根据字段集合组装 JSON schema 主从表结构从表用到
     *
     * @param entityDescribe - 实体描述
     * @param tableFieldList - 有效的数据库表字段信息
     * @return JSONObject - JsonSchema
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/24 8:50
     */
    public static JSONObject getChildJsonSchemaByTableFieldList(final String entityDescribe, List<TableFields> tableFieldList) {
        // 必填字段
        List<String> requiredArrayList = new ArrayList<>();
        // 公共属性
        List<BaseCommonProperty> propertyArrayList = new ArrayList<>();
        // 字典项 服务类
        ISysDictService sysDictService = SpringContextUtils.getBean(ISysDictService.class);
        // 校验 ISysDictService 是否获取成功
        ArgumentResponseEnum.NULL_POINTER_EXCEPTION.assertNotNull(sysDictService);
        for (TableFields item : tableFieldList) {
            String field = item.getFieldName();
            // 主键字段
            if (DataBaseConstant.P_KEY.equals(field)) {
                continue;
            }
            // 获取 required
            if (DataBaseConstant.ONE.equals(String.valueOf(item.getFieldMustInput()))) {
                requiredArrayList.add(field);
            }
            // 表单控件类型
            String filedShowType = item.getFieldShowType();
            // 字典 code
            String dictCode = item.getDictField();
            // 字段备注
            String title = item.getFieldTxt();
            BaseCommonProperty baseCommonProperty;
            if (OnlineDataBaseHandler.isNumberField(item.getFieldType())) {
                // 数字类型
                baseCommonProperty = new NumberPropertyBase(field, title, DataBaseConstant.NUMBER);
            } else {
                if (hasDictConfig(filedShowType)) {
                    // 字典 TODO:This 此处只处理数据字典 没处理字典表
                    List<DictVO> include = sysDictService.queryDictItemsByDictCode(dictCode);
                    baseCommonProperty = new StringPropertyBase(field, title, filedShowType, item.getFieldLength(), include);
                } else {
                    baseCommonProperty = new StringPropertyBase(field, title, filedShowType, item.getFieldLength());
                }
            }
            baseCommonProperty.setOrder(item.getSortOrder());
            propertyArrayList.add(baseCommonProperty);
        }
        return JsonSchemaUtil.getChildJsonSchema(entityDescribe, requiredArrayList, propertyArrayList);
    }

    /**
     * 获取 EditableTable 列的 JSON 数据
     *
     * @param tableFieldList - 数据库表字段信息
     * @param disabledList   - 禁用数据库表字段
     * @return JSONArray - EditableTable 列的 JSON 数据
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/24 11:36
     */
    public static JSONArray getEditableTableColumnsJson(List<TableFields> tableFieldList, List<String> disabledList) {
        JSONArray columnsJsonArray = new JSONArray();
        for (TableFields tableFields : tableFieldList) {
            String field = tableFields.getFieldName();
            // 主键不处理
            if (DataBaseConstant.P_KEY.equals(field)) {
                continue;
            }
            JSONObject columnsJson = new JSONObject();
            if (disabledList.contains(field)) {
                columnsJson.put("disabled", true);
            }
            columnsJson.put("title", tableFields.getFieldTxt());
            columnsJson.put("key", field);
            columnsJson.put("width", "186px");
            // 行编辑扩展
            String viewType = getEditableTableColumnsType(tableFields);
            columnsJson.put("type", viewType);
            if ("file".equals(viewType) || ControlTypeConstant.IMAGE.equals(viewType)) {
                columnsJson.put("responseName", "message");
                columnsJson.put("token", true);
            }
            if (ControlTypeConstant.SWITCH.equals(viewType)) {
                // 开关
                columnsJson.put("type", ControlTypeConstant.CHECK_BOX);
                JSONArray customValue = new JSONArray();
                if (ConvertUtils.isEmpty(tableFields.getFieldExtendJson())) {
                    customValue.add(CommonConstant.TO_UPPER_CASE_Y);
                    customValue.add(CommonConstant.TO_UPPER_CASE_N);
                } else {
                    customValue = JSONArray.parseArray(tableFields.getFieldExtendJson());
                }
                columnsJson.put("customValue", customValue);
            }
            if (ControlTypeConstant.POPUP.equals(viewType)) {
                // 弹出框
                columnsJson.put("popupCode", tableFields.getDictTable());
                columnsJson.put("orgFields", tableFields.getDictField());
                columnsJson.put("destFields", tableFields.getDictText());
                String backFields = tableFields.getDictText();
                if (backFields != null && !backFields.equals(DataBaseConstant.EMPTY)) {
                    List<String> hiddenFields = new ArrayList<>();
                    String[] dictTextArray = backFields.split(DataBaseConstant.COMMA);
                    for (String dictText : dictTextArray) {
                        if (existFieldName(dictText, tableFieldList)) {
                            // 如果现有的列 有此配置的列 跳过
                            continue;
                        }
                        hiddenFields.add(dictText);
                        JSONObject hiddenColumnsJson = new JSONObject();
                        hiddenColumnsJson.put("title", dictText);
                        hiddenColumnsJson.put("key", dictText);
                        hiddenColumnsJson.put("type", ControlTypeConstant.HIDDEN);
                        columnsJsonArray.add(hiddenColumnsJson);
                    }
                }
            }
            columnsJson.put("defaultValue", tableFields.getFieldDefaultValue());
            columnsJson.put("fieldDefaultValue", tableFields.getFieldDefaultValue());
            columnsJson.put("placeholder", "请输入" + tableFields.getFieldTxt());
            columnsJson.put("validateRules", getValidateRules(tableFields));
            // 判断是否需要处理字典配置
            if (hasDictConfig(tableFields.getFieldShowType())) {
                List<DictVO> include = queryDictFieldOptions(tableFields);
				/*for (DictVO dict : include) {
                    columnsJson.put("title", dict.getText());
				}*/
                columnsJson.put("options", include);
                if ("list_multi".equals(tableFields.getFieldShowType())) {
                    // 多选框设定长度 防止控件变形
                    columnsJson.put("width", "230px");
                }
            }
            columnsJsonArray.add(columnsJson);
        }
        return columnsJsonArray;
    }

    /**
     * 获取查询列表的条件SQL
     *
     * @param tableName      - 数据库表表名
     * @param tableFieldList - 数据库表字段信息
     * @param params         - 参数键值对
     * @return String - SQL
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/27 16:36
     */
    public static String getQueryListDataCondition(final String tableName, List<TableFields> tableFieldList, Map<String, Object> params) {
        StringBuilder structuredQueryLanguage = new StringBuilder();
        StringBuilder selectField = new StringBuilder();
        for (TableFields tableFields : tableFieldList) {
            String field = tableFields.getFieldName();
            String fieldType = tableFields.getFieldType();
            // 排除不对外展示字段
            if (CommonConstant.INTEGER_YES.equals(tableFields.getIsShowList())) {
                selectField.append(DataBaseConstant.COMMA).append(field);
            }
            // 对于外键字段添加逻辑处理
            if (ConvertUtils.isNotEmpty(tableFields.getMainField())) {
                boolean isString = !OnlineDataBaseHandler.isNumberField(fieldType);
                String fieldCondition = QueryGenerator.getSingleQueryConditionStructuredQueryLanguage(field, DataBaseConstant.EMPTY, params.get(field), isString);
                if (!DataBaseConstant.EMPTY.equals(fieldCondition)) {
                    structuredQueryLanguage.append(DataBaseConstant.SQL_AND).append(fieldCondition);
                }

            }
            // 查询条件字段
            if (CommonConstant.INTEGER_YES.equals(tableFields.getIsQuery())) {
                if (DataBaseConstant.QUERY_MODE_SINGLE.equals(tableFields.getQueryMode())) {
                    // 单条件查询
                    if (params.get(field) == null) {
                        continue;
                    }
                    boolean isString = !OnlineDataBaseHandler.isNumberField(fieldType);
                    String fieldCondition = QueryGenerator.getSingleQueryConditionStructuredQueryLanguage(field, DataBaseConstant.EMPTY, params.get(field), isString);
                    if (DataBaseConstant.EMPTY.equals(fieldCondition)) {
                        continue;
                    }
                    structuredQueryLanguage.append(DataBaseConstant.SQL_AND).append(fieldCondition);
                } else {
                    // 始
                    Object beginValue = params.get(field + DataBaseConstant.SUFFIX_START);
                    if (beginValue != null) {
                        structuredQueryLanguage.append(DataBaseConstant.SQL_AND).append(field).append(DataBaseConstant.GREATER_THAN_OR_EQUAL_TO);
                        if (OnlineDataBaseHandler.isNumberField(fieldType)) {
                            structuredQueryLanguage.append(beginValue);
                        } else {
                            structuredQueryLanguage.append(DataBaseConstant.SINGLE_QUOTE).append(beginValue).append(DataBaseConstant.SINGLE_QUOTE);
                        }
                    }
                    // 终
                    Object endValue = params.get(field + DataBaseConstant.SUFFIX_END);
                    if (endValue != null) {
                        structuredQueryLanguage.append(DataBaseConstant.SQL_AND).append(field).append(DataBaseConstant.LESS_THAN_OR_EQUAL_TO);
                        if (OnlineDataBaseHandler.isNumberField(fieldType)) {
                            structuredQueryLanguage.append(endValue);
                        } else {
                            structuredQueryLanguage.append(DataBaseConstant.SINGLE_QUOTE).append(endValue).append(DataBaseConstant.SINGLE_QUOTE);
                        }
                    }
                }
            }
        }
        return DataBaseConstant.SQL_SELECT + DataBaseConstant.P_KEY + selectField.toString() + DataBaseConstant.SQL_FROM + getRealTableName(tableName) + DataBaseConstant.SQL_WHERE_TRUE + structuredQueryLanguage.toString();
    }

    /**********************************************************************************************/

    /**
     * 获取页面查询参数
     *
     * @param request - HttpServletRequest
     * @return
     */
    public static Map<String, Object> getParameterMap(HttpServletRequest request) {
        // 参数Map
        Map<?, ?> properties = request.getParameterMap();
        // 返回值Map
        Map<String, Object> returnMap = new HashMap<>(16);
        Iterator<?> entries = properties.entrySet().iterator();

        Map.Entry<String, Object> entry;
        String name;
        String value = DataBaseConstant.EMPTY;
        Object valueObj;
        while (entries.hasNext()) {
            entry = (Map.Entry<String, Object>) entries.next();
            name = entry.getKey();
            valueObj = entry.getValue();
            if ("_t".equals(name) || null == valueObj) {
                value = DataBaseConstant.EMPTY;
            } else if (valueObj instanceof String[]) {
                String[] values = (String[]) valueObj;
                for (String stringValue : values) {
                    value = stringValue + DataBaseConstant.COMMA;
                }
                value = value.substring(0, value.length() - 1);
            } else {
                value = valueObj.toString();
            }
            returnMap.put(name, value);
        }
        return returnMap;
    }

    /**
     * 判断 Class 或是 Spring 的 Bean 是否存在
     *
     * @param formEnhanceJava - Java 增强
     * @return Boolean
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/27 17:02
     */
    public static Boolean checkClassOrSpringBeanIsExist(FormEnhanceJava formEnhanceJava) {
        String javaType = formEnhanceJava.getJavaType();
        String javaValue = formEnhanceJava.getJavaValue();
        if (ConvertUtils.isNotEmpty(javaValue)) {
            try {
                // Class
                if (CommonConstant.CLASS.equals(javaType)) {
                    Class clazz = Class.forName(javaValue);
                    if (clazz == null || clazz.newInstance() == null) {
                        return Boolean.FALSE;
                    }
                }
                // Spring 的 Bean
                if (CommonConstant.SPRING.equals(javaType)) {
                    Object obj = SpringContextUtils.getBean(javaValue);
                    if (obj == null) {
                        return Boolean.FALSE;
                    }
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return Boolean.FALSE;
            }
        }
        return Boolean.TRUE;
    }

    /**
     * 字符串集合排序 不比较长度
     *
     * @param list -  字符串集合
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/27 17:02
     */
    public static void sortStringList(List<String> list) {
        list.sort((o1, o2) -> {
            if (o1 == null || o2 == null) {
                return -1;
            }
            if (o1.compareTo(o2) > 0) {
                return 1;
            }
            if (o1.compareTo(o2) < 0) {
                return -1;
            }
            if (o1.compareTo(o2) == 0) {
                return 0;
            }
            return 0;
        });
    }

    /**
     * 字符串集合排序 优先比较长度
     *
     * @param list -  字符串集合
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/27 17:02
     */
    public static void sortStringListByLength(List<String> list) {
        list.sort((o1, o2) -> {
            if (o1 == null || o2 == null) {
                return -1;
            }
            if (o1.length() > o2.length()) {
                return 1;
            }
            if (o1.length() < o2.length()) {
                return -1;
            }
            if (o1.compareTo(o2) > 0) {
                return 1;
            }
            if (o1.compareTo(o2) < 0) {
                return -1;
            }
            if (o1.compareTo(o2) == 0) {
                return 0;
            }
            return 0;
        });
    }

    /**
     * JavaScript 增强
     *
     * @param enhanceJavaScript - JavaScript 增强
     * @param formButtonList    - 表单按钮
     * @return String
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/17 16:51
     */
    public static String overwriteJs(String enhanceJavaScript, List<FormButton> formButtonList) {
        enhanceJavaScript = overwriteJavaScriptByButtonStyle(enhanceJavaScript, formButtonList);
        for (String temp : ENHANCE_JAVA_SCRIPT_BUTTON_CODE) {
            if ("beforeAdd,afterAdd,mounted,created".contains(temp)) {
                Pattern p = Pattern.compile(DataBaseConstant.LEFT_BRACKET + temp + "\\s*\\(\\)\\s*\\{)");
                Matcher m = p.matcher(enhanceJavaScript);
                if (m.find()) {
                    enhanceJavaScript = enhanceJavaScript.replace(m.group(0), temp + "(that){const getAction=this._getAction,postAction=this._postAction,deleteAction=this._deleteAction;");
                }
            } else {
                enhanceJavaScript = getEnhanceJavaScriptString(enhanceJavaScript, temp);
            }
        }
        return returnEnhanceJsClass(enhanceJavaScript);

    }

    /**
     * 数据库表子表 JavaScript 增强生成（change方法命名： {子表名}_onlineChange）
     *
     * @param formEnhanceJavaScript - 表单 JavaScript 增强
     * @param tableName             - 数据库表名称
     * @param tableFieldList        - 数据库表字段信息
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/17 16:51
     */
    public static void overwriteJavaScriptForChildTable(FormEnhanceJavaScript formEnhanceJavaScript, String tableName, List<TableFields> tableFieldList) {
        if (formEnhanceJavaScript == null || ConvertUtils.isEmpty(formEnhanceJavaScript.getJavaScriptContent())) {
            return;
        }
        String enhanceJavaScript = formEnhanceJavaScript.getJavaScriptContent();
        Pattern p = Pattern.compile(DataBaseConstant.LEFT_BRACKET + tableName + "_" + CommonConstant.ONLINE_JAVA_SCRIPT_CHANGE_FUNCTION_NAME + "\\s*\\(\\)\\s*\\{)");
        Matcher m = p.matcher(enhanceJavaScript);
        if (m.find()) {
            enhanceJavaScript = enhanceJavaScript.replace(m.group(0), tableName + "_" + CommonConstant.ONLINE_JAVA_SCRIPT_CHANGE_FUNCTION_NAME + "(){const getAction=this._getAction,postAction=this._postAction,deleteAction=this._deleteAction;");
            for (TableFields field : tableFieldList) {
                Pattern p1 = Pattern.compile(DataBaseConstant.LEFT_BRACKET + field.getFieldName() + "\\s*\\(\\))");
                Matcher m1 = p1.matcher(enhanceJavaScript);
                if (m1.find()) {
                    enhanceJavaScript = enhanceJavaScript.replace(m1.group(0), field.getFieldName() + "(that,event)");
                }
            }
        }
        formEnhanceJavaScript.setJavaScriptContent(enhanceJavaScript);
    }

    /**
     * 数据库表 JavaScript 增强生成（change方法命名： onlineChange）
     *
     * @param formEnhanceJavaScript - 表单 JavaScript 增强
     * @param tableName             - 数据库表名称
     * @param tableFieldList        - 数据库表字段信息
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/17 16:51
     */
    public static void overwriteJavaScriptForTable(FormEnhanceJavaScript formEnhanceJavaScript, String tableName, List<TableFields> tableFieldList) {
        if (formEnhanceJavaScript == null || ConvertUtils.isEmpty(formEnhanceJavaScript.getJavaScriptContent())) {
            return;
        }
        String enhanceJavaScript = formEnhanceJavaScript.getJavaScriptContent();
        // 处理主表 onlineChange 方法 【change方法命名： onlineChange】
        Pattern p = Pattern.compile("([^_]" + CommonConstant.ONLINE_JAVA_SCRIPT_CHANGE_FUNCTION_NAME + "\\s*\\(\\)\\s*\\{)");
        Matcher m = p.matcher(enhanceJavaScript);
        if (m.find()) {
            enhanceJavaScript = enhanceJavaScript.replace(m.group(0), CommonConstant.ONLINE_JAVA_SCRIPT_CHANGE_FUNCTION_NAME + "(){const getAction=this._getAction,postAction=this._postAction,deleteAction=this._deleteAction;");
            for (TableFields field : tableFieldList) {
                Pattern p1 = Pattern.compile(DataBaseConstant.LEFT_BRACKET + field.getFieldName() + "\\s*\\(\\))");
                Matcher m1 = p1.matcher(enhanceJavaScript);
                if (m1.find()) {
                    enhanceJavaScript = enhanceJavaScript.replace(m1.group(0), field.getFieldName() + "(that,event)");
                }
            }
        }
        formEnhanceJavaScript.setJavaScriptContent(enhanceJavaScript);
        replaceShowMethod(formEnhanceJavaScript);
        overwriteJavaScriptForChildTable(formEnhanceJavaScript, tableName, tableFieldList);
    }

    /**
     * 替换显示方法
     *
     * @param formEnhanceJavaScript - JavaScript 增强 PO
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/17 16:51
     */
    public static void replaceShowMethod(FormEnhanceJavaScript formEnhanceJavaScript) {
        String enhanceJavaScript = formEnhanceJavaScript.getJavaScriptContent();
        String temp = "show";
        Pattern p = Pattern.compile(DataBaseConstant.LEFT_BRACKET + temp + "\\s*\\(\\)\\s*\\{)");
        Matcher m = p.matcher(enhanceJavaScript);
        if (m.find()) {
            enhanceJavaScript = enhanceJavaScript.replace(m.group(0), temp + "(that){const getAction=this._getAction,postAction=this._postAction,deleteAction=this._deleteAction;");
        }
        formEnhanceJavaScript.setJavaScriptContent(enhanceJavaScript);
    }

    /**
     * 在 enhanceJavaScript 外面套一层 class 对象
     *
     * @param enhanceJavaScript - JavaScript 增强
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/17 16:51
     */
    public static String returnEnhanceJsClass(String enhanceJavaScript) {
        log.info("最终的增强JS", enhanceJavaScript);
        return "class OnlineEnhanceJs{constructor(getAction,postAction,deleteAction){this._getAction=getAction;this._postAction=postAction;this._deleteAction=deleteAction;}" + enhanceJavaScript + "}";
    }

    /**
     * 根据按钮类型内置方法参数
     *
     * @param enhanceJavaScript - JavaScript 增强
     * @param formButtonList    - 表单按钮
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/17 16:51
     */
    public static String overwriteJavaScriptByButtonStyle(String enhanceJavaScript, List<FormButton> formButtonList) {
        if (formButtonList != null) {
            for (FormButton button : formButtonList) {
                String temp = button.getButtonCode();
                if ("link".equals(button.getButtonStyle())) {
                    enhanceJavaScript = getEnhanceJavaScriptString(enhanceJavaScript, temp);
                } else if ("button".equals(button.getButtonStyle()) || "form".equals(button.getButtonStyle())) {
                    Pattern p = Pattern.compile(DataBaseConstant.LEFT_BRACKET + temp + "\\s*\\(\\)\\s*\\{)");
                    Matcher m = p.matcher(enhanceJavaScript);
                    if (m.find()) {
                        enhanceJavaScript = enhanceJavaScript.replace(m.group(0), temp + "(that){const getAction=this._getAction,postAction=this._postAction,deleteAction=this._deleteAction;");
                    }
                }
            }
        }
        return enhanceJavaScript;
    }

    /**
     * 拼接分类字典表的 查询条件 online 分类字典树控件用到
     *
     * @param dictCode - 字典编码
     * @return String -  SQL
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/27 16:55
     */
    public static String getCategoryConditionStructuredQueryLanguage(String dictCode) {
        if (dictCode == null || DataBaseConstant.EMPTY.equals(dictCode) || DataBaseConstant.ZERO.equals(dictCode)) {
            return DataBaseConstant.EMPTY;
        }
        return DataBaseConstant.DICT_CODE_FIELD + DataBaseConstant.SQL_LIKE + DataBaseConstant.SINGLE_QUOTE + dictCode + DataBaseConstant.PERCENT + DataBaseConstant.SINGLE_QUOTE;
    }

    /**
     * 获取是图片的列集合（Excel 导入）
     *
     * @param tableFieldList - 数据库表字段信息
     * @return List<String> - 是图片的列集合
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/27 15:16
     */
    public static List<String> getImageColumnList(List<TableFields> tableFieldList) {
        List<String> imageColumnArrayList = new ArrayList<>();
        for (TableFields field : tableFieldList) {
            if (ControlTypeConstant.IMAGE.equals(field.getFieldShowType())) {
                imageColumnArrayList.add(field.getFieldTxt());
            }
        }
        return imageColumnArrayList;
    }

    /**
     * 获取子表是图片的列集合（Excel 导入）
     *
     * @param tableFieldList - 数据库表字段信息
     * @return List<String> - 是图片的列集合
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/10/27 15:16
     */
    public static List<String> getChildImageColumnList(List<TableFields> tableFieldList, final String tableName) {
        List<String> imageColumnArrayList = new ArrayList<>();
        for (TableFields field : tableFieldList) {
            if (ControlTypeConstant.IMAGE.equals(field.getFieldShowType())) {
                imageColumnArrayList.add(tableName + DataBaseConstant.UNDERSCORE + field.getFieldTxt());
            }
        }
        return imageColumnArrayList;
    }

}
